package com.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.junit.Before;
import org.junit.Test;

import com.demo.dao.TestDao;
import com.demo.dao.impl.TestDaoImpl;
import com.demo.proxy.TestInvocationHandler;

public class TestProxy {
	
	private static TestDao dao;
	
	@Before
	public void before(){
		dao = new TestDaoImpl();
	}
	
	@Test
	public void test3() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Class<?> proxyClass = Proxy.getProxyClass(TestProxy.class.getClassLoader(), new Class<?>[]{TestDao.class});
		//代理类生成的过程主要包括两部：①代理类字节码的生成   ②把字节码通过传入的类加载器加载到虚拟机中
		final Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
		final InvocationHandler handler = new TestInvocationHandler(dao);
		TestDao testDao = (TestDao)constructor.newInstance(handler);
		testDao.delete();
		//System.out.println(new Class<?>[]{TestDao.class}.length);
	}

	@Test
	public void test2(){
		System.out.println(TestProxy.class.getClassLoader());
		TestDao proxy = (TestDao)Proxy.newProxyInstance(TestProxy.class.getClassLoader(), new Class<?>[]{TestDao.class}, new TestInvocationHandler(dao));
		proxy.update();
	}
	
	@Test
	public void test(){
		TestDao dao = create(TestDao.class);
		dao.insert();
		
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T  create(Class<?> interfaceClass){
		return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				String methodName = method.getName();
				System.out.println(methodName + "开始时间:" + System.currentTimeMillis());
				Object obj = method.invoke(dao, args);
				System.out.println(methodName + "结束时间:" + System.currentTimeMillis());
				return obj;
			}
		});
	}
}
